#ifndef LIBCO_TIMER_H
#define LIBCO_TIMER_H

#include <cstdint>
#include <functional>
#include <memory>
#include <set>
#include "util.h"

namespace libco{

class TimerManager;

class Timer {
friend class TimerManager;

private:

    typedef std::function<void()> basefunc;
    bool m_recurring; 
    uint64_t m_next;
    uint64_t m_ms;
    std::function<void()> m_cb;
    TimerManager* m_manager;

private:
    typedef std::shared_ptr<Timer> ptr;
    Timer(uint64_t ms, bool recurring, std::function<void()>, TimerManager* timermgr);
    Timer(uint64_t next);

private:
    struct cmp {
        bool operator()(const ptr& l, const ptr& r) const;
    };

};

class TimerManager {
friend class timer;

protected:
    typedef std::function<void()> basefunc;
    std::set<Timer::ptr, Timer::cmp> m_timers;
    RWMutex m_rwmutex;

public:
    Timer::ptr addTimer(uint64_t ms, basefunc cb, bool recurring = false);

    void addTimer(Timer::ptr t, RWMutex::WriteLock& wlock);

    void listAllExpired(std::vector<basefunc>& expired_cb_vec);

    uint64_t getNextTimerMs();
};

} // namespace libco

#endif